package org.softmed.rest.server.xstream;

import java.util.List;
import org.softmed.persistence.PersistenceManager;
import org.softmed.reflection.utils.FieldInfo;
import org.softmed.reflection.utils.ReflectionUtil;
import org.softmed.rest.config.Application;
import org.softmed.rest.generation.ScafoldFacade;
import org.softmed.rest.generation.fields.FieldNameList;
import org.softmed.rest.generation.fields.GenerationConfig;
import org.softmed.rest.generation.scafold.AppConfig;
import org.softmed.rest.generation.xml.XMLMarshaller;
import com.thoughtworks.xstream.XStream;

public class DefaultToXMLListItemConverter implements XMLMarshaller {

	ReflectionUtil util = new ReflectionUtil();
	private XStream streamer;

	public void setup(Class type, PersistenceManager odbUtil, Application app,
			Object... options) throws Throwable {
		streamer = XStreamManager.getXStream();

		streamer.registerConverter(new SimpleListConverter());
		streamer.registerConverter(new DateConverter());
		streamer.registerConverter(new BigIntegerConverter());
		streamer.registerConverter(new BigDecimalConverter());
		// streamer.registerConverter(new TimestampConverter());

		// Class<?> type = obj.getClass();

		if (List.class.isAssignableFrom(type))
			return;
		// return streamer.toXML(obj);

		AppConfig genApp = ScafoldFacade.getApp(app);
		GenerationConfig genCfg = genApp.getGenerationConfig();

		if (genCfg.getAlias(type) != null)
			streamer.alias(genCfg.getAlias(type), type);
		else
			streamer.alias(util.getHifenizedName(type.getSimpleName()), type);

		FieldInfo pkinfo = odbUtil.getPrimaryKeyInfo(type);
		if (pkinfo != null)
			streamer.useAttributeFor(pkinfo.getDeclaringClass(), pkinfo
					.getName());

		Class parent = type;
		do {
			FieldNameList attributeFields = genCfg.getAttributeFields(parent);
			List<String> attributes = null;
			if (attributeFields != null)
				attributes = attributeFields.getFieldNames();

			FieldNameList omitedFields = genCfg.getOmitedFields(parent);
			List<String> omited = null;
			if (omitedFields != null)
				omited = omitedFields.getFieldNames();

			// hide list items and other fields
			Class fieldType = null;
			ReflectionUtil util = new ReflectionUtil();
			List<FieldInfo> fields;
			try {
				List<String> nonDisclosedFields = util
						.getNonDeclaredFieldNames(parent);
				for (String fieldName : nonDisclosedFields) {
					streamer.omitField(parent, fieldName);
				}

				fields = util.getDeclaredFieldInfos(parent);
				for (FieldInfo fieldInfo : fields) {

					String alias = genCfg.getFieldAlias(parent, fieldInfo
							.getName());
					if (alias == null)
						alias = util.getHifenizedName(fieldInfo.getName());

					if (attributes != null
							&& attributes.contains(fieldInfo.getName())) {
						streamer.useAttributeFor(parent, fieldInfo.getName());
//						streamer.aliasAttribute(parent, fieldInfo.getName(),
//								alias);
						streamer.aliasField(alias, parent, fieldInfo.getName());
					} else
						streamer.aliasField(alias, parent, fieldInfo.getName());

					if (omited != null && omited.contains(fieldInfo.getName())) {
						streamer.omitField(parent, fieldInfo.getName());
						continue;
					}

					if (attributes != null) {
						if (attributes.contains(fieldInfo.getName()))
							continue;
					}

					if (pkinfo != null)
						if (pkinfo.getName().equals(fieldInfo.getName()))
							continue;

					streamer.omitField(parent, fieldInfo.getName());

				}
			} catch (Throwable e) {
				e.printStackTrace();
			}

			parent = parent.getSuperclass();
		} while (parent != null && parent != Object.class);
	}

	@Override
	public String toXML(Object obj, PersistenceManager odbUtil,
			Application app, Object... options) throws Throwable {

		return streamer.toXML(obj);
	}

	public DefaultToXMLListItemConverter clone() {
		return new DefaultToXMLListItemConverter();
	}

}
